using System.Collections.Generic;
using System.Reflection;
using System.Web.Mvc;
using Spark.Web.Mvc;
using Spark;
using Spark.Compiler;
using Spark.FileSystem;
using Nemerle.Contrib;

namespace NRails.Spark
{
    public static class SparkNemerleEngineStarter
    {
        public static ConfigureContainer(container : ISparkServiceContainer) : ISparkServiceContainer 
        {
            container.SetServiceBuilder.[IViewEngine](c => SparkViewFactory(c.GetService.[ISparkSettings]()));
            container.SetServiceBuilder.[ISparkViewEngine](c => SparkViewEngine() with
                         {
                             LanguageFactory = c.GetService.[ISparkLanguageFactory]();
                             ExtensionFactory = c.GetService.[ISparkExtensionFactory]();
                         });
            container.SetServiceBuilder.[ISparkLanguageFactory](_ => NemerleLanguageFactory());
            container.SetServiceBuilder.[ISparkExtensionFactory](_ => NRailsExtensionFactory());
            container
        }

        public static CreateContainer() : ISparkServiceContainer 
        {
            ConfigureContainer(SparkServiceContainer());
        }

        public static CreateContainer(settings : ISparkSettings ) : ISparkServiceContainer 
        {
            ConfigureContainer(SparkServiceContainer(settings));
        }

        /// <summary>
        /// Creates a spark IViewEngine with Nemerle as the default language.
        /// Settings come from config or are defaulted.
        /// </summary>
        /// <returns>An IViewEngine interface of the SparkViewFactory</returns>
        public static CreateViewEngine() : IViewEngine
        {
            CreateContainer().GetService.[IViewEngine]();
        }

        /// <summary>
        /// Creates a spark IViewEngine with Nemerle as the default language.
        /// </summary>
        /// <param name="settings">Typically an instance of SparkSettings object</param>
        /// <returns>An IViewEngine interface of the SparkViewFactory</returns>
        public static CreateViewEngine(settings : ISparkSettings) : IViewEngine
        {
            CreateContainer(settings).GetService.[IViewEngine]();
        }

        /// <summary>
        /// Installs the Nemerle view engine. Settings come from config or are defaulted.
        /// </summary>
        public static RegisterViewEngine() : void
        {
            ViewEngines.Engines.Add(CreateViewEngine());
        }

        /// <summary>
        /// Installs the Nemerle view engine. Settings passed in.
        /// </summary>
        public static RegisterViewEngine(settings : ISparkSettings) : void 
        {
            ViewEngines.Engines.Add(CreateViewEngine(settings));
        }

        /// <summary>
        /// Installs the Spark view engine. Service container passed in.
        /// </summary>
        public static RegisterViewEngine(container : ISparkServiceContainer) : void 
        {
            ViewEngines.Engines.Add(container.GetService.[IViewEngine]());
        }

        /// <summary>
        /// Installs the Nemerle view engine. Settings come from config or are defaulted.
        /// </summary>
        /// <param name="engines">Typically in the ViewEngines.Engines collection</param>
        public static RegisterViewEngine(engines : ICollection[IViewEngine]) : void 
        {
            engines.Add(CreateViewEngine());
        }

        /// <summary>
        /// Installs the Nemerle view engine. Settings passed in.
        /// </summary>
        /// <param name="engines">Typically in the ViewEngines.Engines collection</param>
        /// <param name="settings">Typically an instance of SparkSettings object</param>
        public static RegisterViewEngine(engines : ICollection[IViewEngine], settings : ISparkSettings) : void
        {
            engines.Add(CreateViewEngine(settings));
        }

        /// <summary>
        /// Install the view engine from the container. Typical usage is to call CreateContainer,
        /// provide additinal service builder functors to override certain classes, then call this
        /// method.
        /// </summary>
        /// <param name="engines">Typically the ViewEngines.Engines collection</param>
        /// <param name="container">A service container, often created with CreateContainer</param>
        public static RegisterViewEngine(engines : ICollection[IViewEngine], container : ISparkServiceContainer) : void 
        {
            engines.Add(container.GetService.[IViewEngine]());
        }
    }
}